#include "CodificadorVideo.h"
#include <iostream>
using std::cerr;
using std::cout;
using std::endl;

CodificadorVideo::CodificadorVideo() {
	codec = NULL;
	encoder_Ctx = avcodec_alloc_context();
}

void CodificadorVideo::registrar_codecs() {
	av_register_all(); //register the codecs on the system.
}

bool CodificadorVideo::busca_encoder() {
	codec = avcodec_find_encoder(CODEC_ID_MPEG2VIDEO);
	if (!codec) {
		cerr << "Encoder no encontrado" << endl;
		return false;
	}
	return true;
}

bool CodificadorVideo::abre_encoder() {
	if (avcodec_open(encoder_Ctx, codec) < 0) {
		cerr << "No se pudo abrir el encoder" << endl;
		return false;
	}
	return true;
}

void CodificadorVideo::ini_contexto(int width, int height) {
	encoder_Ctx->codec_id = CODEC_ID_MPEG2VIDEO;
	encoder_Ctx->codec_type = AVMEDIA_TYPE_VIDEO;
	encoder_Ctx->bit_rate = 160000;
	// La resolución tiene q ser multiplo de dos, (¿porque?))
	encoder_Ctx->width = width;
	encoder_Ctx->height = height;
	
	encoder_Ctx->time_base.den = 25;
	encoder_Ctx->time_base.num = 1;
	// Un i-Frame cada 10 frames
	encoder_Ctx->gop_size = 10;
	encoder_Ctx->pix_fmt = PIX_FMT_YUV420P;
	// just for testing, we also add B frames
	//encoder_Ctx->max_b_frames = 2;
}

void CodificadorVideo::ini_buffer(AVFrame **frameYUV, uint8_t **outbuf, int *outbuf_size) {
	*outbuf_size = avpicture_get_size(PIX_FMT_YUV420P, encoder_Ctx->width, encoder_Ctx->height);
	*outbuf = (uint8_t *) av_malloc(*outbuf_size);
	avpicture_fill((AVPicture *) (*frameYUV), *outbuf, PIX_FMT_YUV420P,	encoder_Ctx->width, encoder_Ctx->height);
}

// Recibe como parametro el frame de la captura de video en formato YUV
// y lo codifica a a mpeg2
bool CodificadorVideo::codificar(AVFrame **frameYUV, uint8_t **outbuf, int *outbuf_size) {
	int size = avcodec_encode_video(encoder_Ctx, *outbuf, *outbuf_size, *frameYUV);
	cout << "Bytes codificados: " << size << endl;
	if(size > 0)
		return true;
	return false;
}

CodificadorVideo::~CodificadorVideo() {
    avcodec_close(encoder_Ctx);
    av_free(encoder_Ctx);
}
